#ifndef Region_First
#define Region_First
#ifdef __GNUG__
#pragma interface
#endif

#include "Rectangle.h"
#include "String.h"

enum RegionOpcode {
	eRgnUnion           = 0,
	eRgnDifference      = 1,
	eRgnRevDifference   = 2,
	eRgnIntersection    = 3,
	eRgnCopy            = 4
};

class Region;
class RegionRectIter;
class OldRegion;        // obsolete

//--- Region -------------------------------------------------------------------

class Region {
public:
	Region();
	Region(short *s, int len);
	Region(const Rectangle &r);
	Region(const Region &r);
	~Region();

	void operator=(const Region &r);

	const Rectangle &BBox() const;
	int GetRects(Rectangle *rp) const;
	int Length() const;

	friend bool operator==(const Region &r1, const Region &r2);
	friend bool operator!=(const Region &r1, const Region &r2);
	bool IsNotEmpty() const;
	bool IsEmpty() const;
	bool ContainsPoint(const Point &p) const;

	friend Region RegionOp(RegionOpcode code, const Region &r1, const Region &r2);
	friend Region Union(const Region &r1, const Region &r2);
	friend Region Intersection(const Region &r1, const Region &r2);
	friend Region Difference(const Region &r1, const Region &r2);
	friend Region SymDifference(const Region &r1, const Region &r2);

	OStream &PrintOn(OStream &os) const;
	IStream &ReadFrom(IStream &is);

	friend OStream& operator<< (OStream &s, const Region &r);
	friend IStream& operator>> (IStream &s, Region &r);

protected:
	void CalcBBox();

protected:
friend RegionRectIter;
	Rectangle bbox;
	short *buf;
	int cap;
};

SimpleMetaDef(Region);

inline const Rectangle &Region::BBox() const
	{ return bbox; }
inline int Region::Length() const
	{ return cap; }
inline Region Union(const Region &r1, const Region &r2)
	{ return RegionOp(eRgnUnion, r1, r2); }
inline Region Intersection(const Region &r1, const Region &r2)
	{ return RegionOp(eRgnIntersection, r1, r2); }
inline Region Difference(const Region &r1, const Region &r2)
	{ return RegionOp(eRgnDifference, r1, r2); }
inline bool operator!=(const Region &r1, const Region &r2)
	{ return !operator==(r1, r2); }
inline bool Region::IsNotEmpty() const
	{ return bbox.IsNotEmpty(); }
inline bool Region::IsEmpty() const
	{ return bbox.IsEmpty(); }
inline OStream& operator<< (OStream &os, const Region &r)
	{ return r.PrintOn(os); }
inline IStream& operator>> (IStream &is, Region &r)
	{ return r.ReadFrom(is); }

//---- RegionRectIter ----------------------------------------------------------

class RegionRectIter {
	short *s;
	int next;
public:
	RegionRectIter(const Region &r);
	bool operator()(Rectangle &r);
};

//---- OldRegion ---------------------------------------------------------------

class OldRegion {
public:
	int size;
	Rectangle *rl, bbox;
public:
	OldRegion();
	OldRegion(const Rectangle &r);
	~OldRegion();
	void Merge(const Rectangle &r);
	Rectangle *GetAt(int ix) const;
	void operator=(const OldRegion &r);
	void Empty();
};

#endif

